// Copyright (c) Microsoft Corporation.  All rights reserved.
#include "Common.h"

typedef struct _SCF_ATTR_ID {
    LPCWSTR pwszValue;
    DWORD dwId;
} SCF_ATTR_ID;

// <btn key="xxx">
const static SCF_ATTR_ID btn_key_ids[] = {
{ L"enter", (DWORD)SCF_BUTTON_SELECT },
{ L"back",  (DWORD)SCF_BUTTON_BACK   },
{ L"left",  (DWORD)SCF_BUTTON_LEFT   },
{ L"right", (DWORD)SCF_BUTTON_RIGHT  },
{ L"home",  (DWORD)SCF_BUTTON_HOME   },
{ NULL, 0 }};

// <content bgfix="xxx">
const static SCF_ATTR_ID content_bgfit_ids[] = {
{ L"s", (DWORD)SCF_BGFIT_SCALE  },
{ L"c", (DWORD)SCF_BGFIT_CENTER },
{ L"t", (DWORD)SCF_BGFIT_TILE   },
{ NULL, 0 }};

// <txt align="xxx">
// <img align="xxx">
const static SCF_ATTR_ID align_ids[] = {
{ L"l", (DWORD)SCF_ALIGN_LEFT   },
{ L"r", (DWORD)SCF_ALIGN_RIGHT  },
{ L"c", (DWORD)SCF_ALIGN_CENTER },
{ NULL, 0 }};

// <img fit="xxx">
const static SCF_ATTR_ID img_fit_ids[] = {
{ L"native", (DWORD)SCF_IMAGEFIT_NATIVE },
{ L"width",  (DWORD)SCF_IMAGEFIT_WIDTH  },
{ L"screen", (DWORD)SCF_IMAGEFIT_SCREEN },
{ L"auto",   (DWORD)SCF_IMAGEFIT_AUTO   },
{ NULL, 0 }};

// <menu selectaction="xxx">
const static SCF_ATTR_ID menu_selectaction_ids[] = {
{ L"target", (DWORD)SCF_SELECTACTION_TARGET },
{ L"menuid", (DWORD)SCF_SELECTACTION_MENUID },
{ NULL, 0 }};

//
// static helper function to look up attribute ID
//
static HRESULT LookupAttrId(LPCWSTR pwszVal, const SCF_ATTR_ID id_table[], DWORD *pdwId)
{
    HRESULT hr = E_INVALIDARG;

    for(const SCF_ATTR_ID *p = id_table; p->pwszValue != NULL; p++)
    {
        //
        // this should be a case-sensitive comparison.
        // doing case-insensitive comparison here to be able to parse SCFs which have
        // attributes something like key="Left" key="Right".
        //
        if (_wcsicmp(pwszVal, p->pwszValue) == 0)
        {
            *pdwId = p->dwId;
            hr = S_OK;
            break;
        }
    }

    return hr;
}

//
// initialize <btn> element
//
HRESULT CScfBtnElement::Initialize(ISAXAttributes *pAttributes)
{
    HRESULT hr = S_OK;
    
    /*
        Attributes:
            key     req
            target  req
    */
    
    wstring wstrKey;
    
    hr = GetSAXAttributeString(L"key", pAttributes, wstrKey, TRUE);
    
    if (SUCCEEDED(hr))
    {
        DWORD dwId = 0;

        hr = LookupAttrId(wstrKey.c_str(), btn_key_ids, &dwId);

        if (SUCCEEDED(hr))
        {
            m_btnKey = (SCF_BUTTON_IDS)dwId;
        }
    }
    
    if (SUCCEEDED(hr))
    {
        hr = GetSAXAttributeUInt(L"target", pAttributes, (UINT *)&m_targetId, TRUE);
    }
    
    return hr;
}

//
// common initialize routine of <content>, <dialog> and <menu>
//
HRESULT CScfContentBase::Initialize(ISAXAttributes *pAttributes)
{
    HRESULT hr = S_OK;

    hr = GetSAXAttributeUInt(L"id", pAttributes, &m_id, TRUE);
    
    if (SUCCEEDED(hr))
    {
        hr = GetSAXAttributeString(L"title", pAttributes, m_title, FALSE);
    }

    return hr;
}

//
// check if this content has reference to the given imgid.
//
BOOL CScfContentBase::HasImageReferenceOf(CONTENT_ID imgid)
{
    BOOL bRet = FALSE;

    for(size_t i = 0; i < m_elems.size(); i++)
    {
        CScfElement *pElement = m_elems[i];
        
        switch(pElement->GetElementType())
        {
            case SCF_IMG_ELEMENT:
            {
                CScfImgElement *pImgElement = (CScfImgElement *)pElement;
                
                if (pImgElement->m_id == imgid)
                {
                    bRet = TRUE;
                    break;
                }
                
                break;
            }
            case SCF_ITEM_ELEMENT:
            {
                CScfItemElement *pItemElement = (CScfItemElement *)pElement;
                
                if (pItemElement->m_imgId == imgid)
                {
                    bRet = TRUE;
                    break;
                }
                
                break;
            }
        }
    }

    return bRet;
}

//
// initialize <content> element
//
HRESULT CScfContentElement::Initialize(ISAXAttributes *pAttributes)
{
    /*
        Attributes:
            id      req
            title   op
            bg      op
            bgfit   op
            menuid  op
    */
    HRESULT hr;

    // ID and title
    hr = __super::Initialize(pAttributes);

    if (SUCCEEDED(hr))
    {
        hr = GetSAXAttributeUInt(L"bg", pAttributes, (UINT *)&m_bg, FALSE);
    }

    if (SUCCEEDED(hr))
    {
        wstring strBgFit;
        HRESULT hrTemp;
        
        hrTemp = GetSAXAttributeString(L"bgfit", pAttributes, strBgFit, TRUE);
        
        if (SUCCEEDED(hrTemp))
        {
            DWORD dwId = 0;

            hrTemp = LookupAttrId(strBgFit.c_str(), content_bgfit_ids, &dwId);

            if (hrTemp == S_OK)
            {
                m_bgfit = (SCF_BGFIT)dwId;
            }
        }
    }
    
    if (SUCCEEDED(hr))
    {
        HRESULT hrTemp;
        
        hrTemp = GetSAXAttributeUInt(L"menuid", pAttributes, (UINT *)&m_menuId, TRUE);
        
        if (SUCCEEDED(hrTemp))
        {
            m_Flags |= SCF_FLAG_MENUID_ATTR;
        }
    }

    return hr;
}

//
// check if this <content> content has reference to the given imgid.
//
BOOL CScfContentElement::HasImageReferenceOf(CONTENT_ID imgid)
{
    BOOL bRet = FALSE;

    if (m_bg == imgid)
    {
        bRet = TRUE;
    }
    else
    {
        bRet = __super::HasImageReferenceOf(imgid);
    }

    return bRet;
}

//
// initialize <dialog> element
//
HRESULT CScfDialogElement::Initialize(ISAXAttributes *pAttributes)
{
    /*
        Attributes:
            id      req
            title   op
            imgid   op
    */
    HRESULT hr;

    // ID and title
    hr = __super::Initialize(pAttributes);
	
    if (SUCCEEDED(hr))
    {
        hr = GetSAXAttributeUInt(L"imgid", pAttributes, (UINT *)&m_imgId, FALSE);
    }

    return hr;
}

//
// check if this <dialog> content has reference to the given imgid.
//
BOOL CScfDialogElement::HasImageReferenceOf(CONTENT_ID imgid)
{
    BOOL bRet = FALSE;

    if (m_imgId == imgid)
    {
        bRet = TRUE;
    }
    else
    {
        bRet = __super::HasImageReferenceOf(imgid);
    }

    return bRet;
}

//
// initialize <txt> element
//
HRESULT CScfTxtElement::Initialize(ISAXAttributes *pAttributes)
{
    /*
        Attributes:
            align   op
            wrap    op
            rgb     op
    */
    
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr))
    {
        HRESULT hrTemp;
        wstring wstrAlign;

        hrTemp = GetSAXAttributeString(L"align", pAttributes, wstrAlign, TRUE);

        if (SUCCEEDED(hrTemp))
        {
            DWORD dwId = 0;

            hrTemp = LookupAttrId(wstrAlign.c_str(), align_ids, &dwId);

            if (hrTemp == S_OK)
            {
                m_align = (SCF_ALIGN)dwId;
            }
        }
    }
    
    if (SUCCEEDED(hr))
    {
        hr = GetSAXAttributeBool(L"wrap", pAttributes, &m_wrap, FALSE);
    }
    
    if (SUCCEEDED(hr))
    {
        HRESULT hrTemp;
        
        hrTemp = GetSAXAttributeRgb(pAttributes, &m_rgb, TRUE);
        
        if (SUCCEEDED(hrTemp))
        {
            m_Flags |= SCF_FLAG_RGB_ATTR;
        }
    }
    
    return hr;
}

//
// initialize <img> element
//
HRESULT CScfImgElement::Initialize(ISAXAttributes *pAttributes)
{
    /*
        Attributes:
            id      req
            align   op
            fit     op
            alt     op
    */
    HRESULT hr = S_OK;
    
    hr = GetSAXAttributeUInt(L"id", pAttributes, &m_id, TRUE);
    
    if (SUCCEEDED(hr))
    {
        HRESULT hrTemp;
        wstring wstrAlign;

        hrTemp = GetSAXAttributeString(L"align", pAttributes, wstrAlign, TRUE);

        if (SUCCEEDED(hrTemp))
        {
            DWORD dwId = 0;

            hrTemp = LookupAttrId(wstrAlign.c_str(), align_ids, &dwId);

            if (hrTemp == S_OK)
            {
                m_align = (SCF_ALIGN)dwId;
            }
        }
    }
    
    if (SUCCEEDED(hr))
    {
        HRESULT hrTemp;
        wstring wstrFit;

        hrTemp = GetSAXAttributeString(L"fit", pAttributes, wstrFit, TRUE);

        if (SUCCEEDED(hrTemp))
        {
            DWORD dwId = 0;

            hrTemp = LookupAttrId(wstrFit.c_str(), img_fit_ids, &dwId);

            if (hrTemp == S_OK)
            {
                m_fit = (SCF_IMAGEFIT)dwId;
            }
        }
    }
    
    /*
    if (SUCCEEDED(hr))
    {
        hr = GetSAXAttributeString(L"alt", pAttributes, m_alt, FALSE);
    }
    */
    
    return hr;
}

//
// initialize <item> element
//
HRESULT CScfItemElement::Initialize(ISAXAttributes *pAttributes)
{
    /*
        Attributes:
            id      op
            target  op
            imgid   op
            def     op
            enable  op
            menuid  op
    */

    HRESULT hr = S_OK;
    
    hr = GetSAXAttributeUInt(L"id", pAttributes, &m_id, FALSE);
    
    if (SUCCEEDED(hr))
    {
        hr = GetSAXAttributeUInt(L"target", pAttributes, (UINT *)&m_targetId, FALSE);
    }

    if (SUCCEEDED(hr))
    {
        hr = GetSAXAttributeUInt(L"imgid", pAttributes, (UINT *)&m_imgId, FALSE);
    }

    if (SUCCEEDED(hr))
    {
        hr = GetSAXAttributeBool(L"def", pAttributes, &m_def, FALSE);
    }
    
    if (SUCCEEDED(hr))
    {
        hr = GetSAXAttributeBool(L"enable", pAttributes, &m_enable, FALSE);
    }
    
    if (SUCCEEDED(hr))
    {
        HRESULT hrTemp;

        hrTemp = GetSAXAttributeUInt(L"menuid", pAttributes, &m_menuId, TRUE);
        
        if (SUCCEEDED(hrTemp))
        {
            m_Flags |= SCF_FLAG_MENUID_ATTR;
        }
    }
    
    return hr;
}

//
// initialize <menu> element
//
HRESULT CScfMenuElement::Initialize(ISAXAttributes *pAttributes)
{
    /*
        Attributes:
            id      req
            title   op
            selectaction op     "target" or "menuid"
    */

    HRESULT hr = S_OK;
    
    hr = GetSAXAttributeUInt(L"id", pAttributes, &m_id, TRUE);

    if (SUCCEEDED(hr))
    {
        hr = GetSAXAttributeString(L"title", pAttributes, m_title, FALSE);
    }

    if (SUCCEEDED(hr))
    {
        HRESULT hrTemp;
        wstring wstrSelectAction;

        hrTemp = GetSAXAttributeString(L"selectaction", pAttributes, wstrSelectAction, TRUE);

        if (SUCCEEDED(hrTemp))
        {
            DWORD dwId = 0;

            hrTemp = LookupAttrId(wstrSelectAction.c_str(), menu_selectaction_ids, &dwId);

            if (SUCCEEDED(hrTemp))
            {
                m_selectaction = (SCF_SELECTACTION)dwId;
            }
        }
    }

    return hr;
}
